iT邦幫忙

2022 iThome 鐵人賽

DAY 3
0

今天我們延續昨天的話題, 把 Day 01 的 Hello world 加上酷炫的 Signal & Slot 吧!

這次因為希望能玩到 Signal & Slot 的深入使用, 所以我打算加了兩層 subClass

但是 Day 01 最後的成果看起來真的讓人覺得煩躁, 因為按鈕跑來跑去, 要上下移動按按鈕很麻煩, 所以在這裡我們加一個空白的 QLabel (blank) 卡在原本 Hello 的位置

import sys
from PySide6 import QtCore, QtWidgets

class MyWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self.isShow = True
        self.text = QtWidgets.QLabel("Hello",
                                    alignment=QtCore.Qt.AlignCenter)
        self.blank = QtWidgets.QLabel("",
                                    alignment=QtCore.Qt.AlignCenter)

        self.button = QtWidgets.QPushButton("Click")
        self.button.clicked.connect(self.isShowOrHide)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.layout.addWidget(self.text)
        self.layout.addWidget(self.blank)
        self.blank.hide()
        self.layout.addWidget(self.button)

    def isShowOrHide(self):
        if(self.isShow):
            self.text.hide()
            self.blank.show()
            self.isShow = False
        else:
            self.text.show()
            self.blank.hide()
            self.isShow = True

if __name__ == "__main__":
    app = QtWidgets.QApplication([])

    widget = MyWidget()
    widget.resize(300, 300)
    widget.show()

    sys.exit(app.exec())

一開始就建好一個要顯示的 QLabel 和卡位用的空白 QLabel, 空白 QLabel 先 hide 藏起來, 之後在函式裡讓兩個 QLabel 交互 show/hide, 讓 click 按鈕能保持在原位
BlankQLabel

接下來的兩層 subclass 我是用 QLineEdit 下去改寫的, 因為 QLabel 看過了, 來使用看看別的元件吧

成果外觀如圖所示
https://ithelp.ithome.com.tw/upload/images/20220905/20151144TEQ4DDb0QZ.png
為了不讓 subWidget1 的文字被 subWidget2 蓋掉, 所以在這裡把 subWidget2 的高度先設定成 100 讓它高一點, 接下來把 subWidget1 的文字使用 setAlignment() 讓文字置於上方中間, 這樣就能看到兩行文字的變化了~

QLineEdit 是個單行的文字輸入框, 但在這裡不需要輸入功能, 所以使用 setDisabled(True) 來將這兩個 QLineEdit 變成不可輸入狀態
https://ithelp.ithome.com.tw/upload/images/20220905/201511444Ulil1ZKBM.png

在這裡我們用 signal&slot 在每次按鈕被點即時改變 SubWidget1 裡的文字
而在 SubWidget1 改變文字當下, SubWidget2 裡變成點一次按鈕就會加一的數字

import sys
from PySide6 import QtCore, QtWidgets
class SubWidget2(QtWidgets.QLineEdit):
    signal_addNum = QtCore.Signal()
    def __init__(self):
        super(SubWidget2, self).__init__()
        self.numbers = 0

    @QtCore.Slot()
    def addNumText(self):
        self.numbers = self.numbers + 1
        self.setText(str(self.numbers))

class SubWidget1(QtWidgets.QLineEdit):
    signal_showText = QtCore.Signal(str)
    def __init__(self):
        super(SubWidget1, self).__init__()
        self.setFixedHeight(100)
        self.subWidget2 = SubWidget2()
        self.subWidget2.setText("SubWidget2")
        self.subWidget2.setDisabled(True)
        self.subWidget2.setAlignment(QtCore.Qt.AlignCenter)
        self.subWidget2.signal_addNum.connect(self.subWidget2.addNumText)

        self.layout = QtWidgets.QHBoxLayout(self)
        self.layout.addWidget(self.subWidget2)

    @QtCore.Slot(str)
    def setTextAB(self, txt : str):
        self.setText(txt)
        self.subWidget2.signal_addNum.emit()

class MyWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self.isShow = True
        self.subWidget1 = SubWidget1()
        self.subWidget1.setText("SubWidget1")
        self.subWidget1.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter)
        self.subWidget1.setDisabled(True)
        self.subWidget1.signal_showText.connect(self.subWidget1.setTextAB)

        self.text = QtWidgets.QLabel("Hello",
                                    alignment=QtCore.Qt.AlignCenter)
        self.blank = QtWidgets.QLabel("",
                                    alignment=QtCore.Qt.AlignCenter)

        self.button = QtWidgets.QPushButton("Click")
        self.button.clicked.connect(self.isShowOrHide)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.layout.addWidget(self.text)
        self.layout.addWidget(self.blank)
        self.blank.hide()
        self.layout.addWidget(self.subWidget1)
        self.layout.addWidget(self.button)

    def isShowOrHide(self):
        if(self.isShow):
            self.text.hide()
            self.blank.show()
            self.isShow = False
            self.subWidget1.signal_showText.emit("A")
        else:
            self.text.show()
            self.blank.hide()
            self.isShow = True
            self.subWidget1.signal_showText.emit("B")

if __name__ == "__main__":
    app = QtWidgets.QApplication([])

    widget = MyWidget()
    widget.resize(300, 300)
    widget.show()

    sys.exit(app.exec())

成果
ohyeah


雖然以這個程式來看 signal&slot 好像也就普普, 但是在大型的專案裡, 要在最上層把訊號傳給某個下層, 尤其是當 class 在不同的 .py 擋, 但訊號要互傳的話, 這個機制就會很方便。


上一篇
【Day02】Signal & Slot
下一篇
【Day04】Dialog 邊緣人對話框
系列文
[Python QT] 玩玩 Pyside 的各種功能31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言